﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using System.Reflection;

namespace FrogEngine
{
	public class ScreenManagerFSM : FSM, IRenderable
	{
		public ScreenManagerFSM()
			: base()
		{
		}

		public ScreenManagerFSM(string fileName)
			: base(fileName)
		{
		}

		public ISet<IFSMState> GetAllStates
		{
			get { return this.States; }
		}

		private bool transitionInProgress = false, leavingDone = false, enteringDone = false;
		private IGameScreen nextScreen;
		public override void Transition(IFSMState nextState)
		{
			if (currentState == null)
			{
				nextScreen = nextState as IGameScreen;
				transitionInProgress = true;
				nextScreen.TransitionCompleted += next_TransitionCompleted;
				leavingDone = true;
				nextState.OnEntering();
			}
			else if (currentState.IsValidTransition(nextState))
			{
				IGameScreen current = currentState as IGameScreen;
				nextScreen = nextState as IGameScreen;
				transitionInProgress = true;

				current.TransitionCompleted += current_TransitionCompleted;
				nextScreen.TransitionCompleted += next_TransitionCompleted;
				current.OnLeaving();
				nextScreen.OnEntering();
			}
			else throw new FSMInvalidTransitionException(currentState, nextState);
		}

		void next_TransitionCompleted(object sender, EventArgs e)
		{
			enteringDone = true;
			if (leavingDone)
			{
				currentState = nextScreen;
				transitionInProgress = false;
				enteringDone = false;
				leavingDone = false;
			}
			nextScreen.TransitionCompleted -= next_TransitionCompleted;
			nextScreen = null;
		}

		void current_TransitionCompleted(object sender, EventArgs e)
		{
			IGameScreen current = sender as IGameScreen;
			leavingDone = true;
			if (enteringDone)
			{
				currentState = nextScreen;
				nextScreen = null;
				transitionInProgress = false;
				enteringDone = false;
				leavingDone = false;
			}
			current.TransitionCompleted -= current_TransitionCompleted;
		}

		public override void Update(GameTime gameTime)
		{
			if (transitionInProgress)
			{
				if (currentState != null)
					currentState.Update(gameTime);
				if (nextScreen != null)
					nextScreen.Update(gameTime);
			}
			else if (currentState != null)
				currentState.Update(gameTime);
		}

		public void Render(GameTime gameTime)
		{
			if (transitionInProgress)
			{
				if (currentState != null)
					(currentState as IGameScreen).Render(gameTime);
				if (nextScreen != null)
					nextScreen.Render(gameTime);
			}
			else if (currentState != null)
				(currentState as IGameScreen).Render(gameTime);
		}

		public override void LoadFSMFromFile(string fileName)
		{
			throw new NotImplementedException();
		}
	}
}
